package org.teremail.smtp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.teremail.smtp.commands.DATACommand;
import org.teremail.smtp.commands.EHLOCommand;
import org.teremail.smtp.commands.EXPNCommand;
import org.teremail.smtp.commands.HELOCommand;
import org.teremail.smtp.commands.HELPCommand;
import org.teremail.smtp.commands.MAILCommand;
import org.teremail.smtp.commands.NOOPCommand;
import org.teremail.smtp.commands.QUITCommand;
import org.teremail.smtp.commands.RCPTCommand;
import org.teremail.smtp.commands.RSETCommand;
import org.teremail.smtp.commands.SMTPCommand;
import org.teremail.smtp.commands.VRFYCommand;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;

/**
 * Parses the incoming smtp command line and produces the appropriate 
 * command object.
 * 
 * @author Michael Barker
 *
 */
public class SMTPCommandParser {

    private final static Map<String,SMTPCommandFactory> factories;
    
    static {
        Map<String,SMTPCommandFactory> m = Maps.newHashMap();
        m.put("HELO", HELOCommand.FACTORY);
        m.put("EHLO", EHLOCommand.FACTORY);
        m.put("MAIL", MAILCommand.FACTORY);
        m.put("RCPT", RCPTCommand.FACTORY);
        m.put("DATA", DATACommand.FACTORY);
        m.put("RSET", RSETCommand.FACTORY);
        m.put("VRFY", VRFYCommand.FACTORY);
        m.put("EXPN", EXPNCommand.FACTORY);
        m.put("NOOP", NOOPCommand.FACTORY);
        m.put("HELP", HELPCommand.FACTORY);
        m.put("QUIT", QUITCommand.FACTORY);
        
        factories = Collections.unmodifiableMap(m);
    }
    
    public static SMTPCommandParser create() {
        return new SMTPCommandParser();
    }

    public SMTPCommand parse(String s) throws UnknownCommandException {
        
        assert s != null;
        
        String[] parts = s.split(" ");
        SMTPCommandFactory cmdFactory = factories.get(parts[0]);
        if (cmdFactory != null) {
            List<String> params = asList(parts, 1);
            return cmdFactory.create(params);
        } else {
            throw new UnknownCommandException(parts[0]);
        }
    }
    
    public static List<String> asList(String[] arr, int offset) {
        List<String> l = new ArrayList<String>();
        for (int i = offset; i < arr.length; i++) {
            l.add(arr[i]);
        }
        return ImmutableList.copyOf(l);
    }

}
